package ferp.android.tasks.local;

import android.os.AsyncTask;
import ferp.android.activities.Ferp;
import ferp.core.log.Log;

import java.util.Iterator;
import java.util.LinkedList;

/**
 * User: olegs
 * Date: 04/09/2014 13:20
 */
public abstract class TaskSerial<Progress, Result> extends AsyncTask<Void, Progress, Result>
{
  public static <Progress, Result> boolean isActive(Class<? extends TaskSerial<Progress, Result>> clazz) {return clazz.isInstance(active);}
  public static TaskSerial active() {return active;}

  public static void cancel(Ferp ferp)
  {
    // remove queued tasks first
    for (Iterator<TaskSerial> i = queue.iterator(); i.hasNext(); /**/)
    {
      TaskSerial task = i.next();

      if (task.ferp == ferp)
      {
        task.cancel(true);
        i.remove();
      }
    }

    // cancel the active task if any
    if (active != null && active.ferp == ferp)
      active.cancel(true);
  }

  public TaskSerial(Ferp ferp)
  {
    this.ferp = ferp;
  }

  public final void executeSerial()
  {
    if (active == null)
    {
      active = this;
      execute();

      Log.debug(Log.TAG, "task " + this + " started");
    }
    else
    {
      queue.add(this);

      Log.debug(Log.TAG, "task " + this + " queued");
    }
  }

  protected Ferp ferp() {return ferp;}

  @Override
  protected final void onPostExecute(Result result)
  {
    doOnPostExecute(result);

    Log.debug(Log.TAG, "task " + this + " finished");

    // next task
    next();
  }

  @Override
  protected final void onCancelled()
  {
    Log.debug(Log.TAG, "task " + this + " canceled");

    // next task
    next();
  }

  // new post execute handler
  protected void doOnPostExecute(Result result) {}

  // serial tasks management
  private static final LinkedList<TaskSerial> queue = new LinkedList<TaskSerial>();
  private static TaskSerial active = null;

  // this is for tracking task by activity
  private final Ferp ferp;

  // start next task from the queue
  private void next()
  {
    active = null;

    if (queue.size() > 0)
      queue.removeFirst().executeSerial();
  }
}
